/**
 * 
 */
package blms.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;

import org.apache.commons.beanutils.PropertyUtils;

import blms.exception.UnknownAttributeException;

/**
 * This class provides a service to access and assign data from/to beans.
 * 
 * @author Thiago Emmanuel Pereira da Cunha Silva, thiago.manel@gmail.com
 */
public class ReflectionHelper {

	/**
	 * Access java bean's field.
	 * 
	 * @param bean
	 *            The java bean
	 * @param attribute
	 *            The name of the field, the bean must be well formatted. If the
	 *            field name is foo then a getFoo method should be provided by
	 *            the bean.
	 * 
	 * @return A string vision of the java bean's field
	 * @throws UnknownAttributeException
	 *             This exception will be throwed when there is a programming
	 *             error, the bean should be declare well formatted get methods.
	 * 
	 */
	public static Object getAttribute(final Object bean, final String attribute)
			throws UnknownAttributeException {
		try {
			return PropertyUtils.getProperty(bean, attribute);
		} catch (final IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (final InvocationTargetException e) {
			throw new RuntimeException(e);
		} catch (final NoSuchMethodException e) {
			throw new UnknownAttributeException(e);
		}
	}

	/**
	 * Assign a value to bean's fields.
	 * 
	 * @param bean
	 *            The java bean
	 * @param attribute
	 *            The name of the field, the bean must be well formatted. If the
	 *            field name is foo then a setFoo method should be provided by
	 *            the bean.
	 * 
	 * @param attributeValue
	 *            The new value.
	 * @throws UnknownAttributeException
	 *             This exception will be throwed when there is a programming
	 *             error, the bean should be declare well formatted set methods.
	 */
	public static void setAttribute(final Object bean, final String attribute,
			final Object attributeValue) throws UnknownAttributeException {
		try {
			PropertyUtils.setProperty(bean, attribute, attributeValue);
		} catch (final IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (final InvocationTargetException e) {
			throw new RuntimeException(e.getCause().getMessage());
		} catch (final NoSuchMethodException e) {
			throw new UnknownAttributeException(e);
		}
	}

	/**
	 * Checks if a bean contains a attribute.
	 * 
	 * @param bean
	 *			The java bean
	 *
	 * @param attribute
	 *          The name of the field, the bean must be well formatted. If the
	 *          field name is foo then a setFoo method should be provided by
	 *          the bean.
	 *          
	 * @param msg
	 * 
	 * @throws UnknownAttributeException
	 * 			   This exception will be throwed when there is a programming
	 *             error, there is not a attribute named @param attribute
	 */
	public static void checkAttribute(final Object bean,
			final String attribute, final String msg)
			throws UnknownAttributeException {
		try {
			final PropertyDescriptor propertyDescriptor = PropertyUtils
					.getPropertyDescriptor(bean, attribute);
			if (propertyDescriptor == null) {
				throw new UnknownAttributeException(msg);
			}

		} catch (final IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (final InvocationTargetException e) {
			throw new RuntimeException(e);
		} catch (final NoSuchMethodException e) {
			throw new UnknownAttributeException(msg, e);
		}
	}

}
